ansible与playbook
===================================================
SYNOPSIS
       ansible <host-pattern> [-f forks] [-m module_name] [-a args]
FILES：
       /etc/ansible/hosts — Default inventory file
       /usr/share/ansible/ — Default module library
       /etc/ansible/ansible.cfg — Config file, used if present
       ~/.ansible.cfg — User config file, overrides the default config if present
------------------------------------------------------------------------------------------------
（1）添加要修改的主机
        ~]# vi /etc/ansible/hosts
        [web]
        172.18.21.72
        172.18.21.73

（2）本机生成秘钥复制到要控制的主机：
        ~]# ssh-keygen -t rsa -P ' '
        ~]# ssh-copy-id -i .ssh/id_rsa.pub root@172.18.21.72
        ~]# ssh-copy-id -i .ssh/id_rsa.pub root@172.18.21.73
        
-bash: ssh: command not found的解决办法
yum -y install openssh-clients
------------------------------------------------------------------------------------------------
ansible的常用模块：

--- ansible-doc  -l：获取模块列表
    ~]# ansible-doc -l

--- ansible-doc -s：查看某个模块的使用方法
    ~]# ansible-doc -s shell

--- ping
    ~]# ansible all -m  ping

--- command：在远程主机运行命令：默认 (default=command)
    ~]# ansible web -m command -a 'ls /var'
    ~]# ansible web -a 'ls /var'
    ~]# ansible all -a 'ls /var'

--- shell：在远程主机在shell进程下运行命令，支持shell特性，如管道等。
    ~]# ansible web -m shell -a 'ls / | grep usr'

--- copy：复制文件到远程
    (1) src=本机文件  dest=远端目录
        ~]# ansible web -m shell -a 'ls / | grep usr'

    (2) content=  dest=
    owner, group, mode 

--- cron：管理计划任务 crontab。
        minute=     # 分钟
        day=           # 天
        month=       # 月
        weekday=    # 周
        hour=           # 小时
        job=            # 执行的命令
        *name=      # 名称
        state=         # 状态
            present：创建
            absent：删除

    ~]# ansible all -a "yum -y install ntpdate"
    ~]# ansible all -m cron -a "minute=*/5 job='/sbin/ntpdate 172.18.0.1 > /dev/null' name=synctime"
    ~]# ansible all -a "crontab -l"
    ~]# ansible all -m cron -a "name=synctime state=absent"

--- fetch：从远程主机获取文件到本地
    ~]#
    ~]# 
ansible 172.18.21.72 -m fetch -a "src=/var/log/message dest=/root/"

--- file：设置文件属性
    (1) 创建链接文件：src=  path= state=link
        ~]# ansible all -m copy -a "src=/etc/fstab dest=/tmp/"
        ~]# ansible all -m file -a "src=/tmp/fstab path=/tmp/fstab.link state=link"

    (2) 修改属性：path=  owner=(chown) mode=(chmod) group= 
        ~]# ansible all -m shell -a "ls -l /tmp | grep fstab"
        ~]# ansible all -m file -a "path=/tmp/fstab owner=mdx mode=777 group=mdx"

    (3) 创建目录：path=  state=directory
        ~]# ansible all -m file -a "path=/tmp/aa state=directory"

--- hostname：管理主机名
    ~}# 

--- pip：Python 库管理

--- yum：Manages packages with the `yum' package manager
        name=：程序包名称，可以带版本号；
        state=
            present, latest # 安装
            absent              # 卸载

    ~]# ansible all -m yum -a "name=nginx state=present"
    ~]# 

--- service：管理服务
        *name=   # 名字
        state=      # 声明
            started     # 开启
            stopped     # 停止
            restarted   # 重启
        enabled=       # 开机启动
        runlevel=       # 运行级别
    ~]# ansible all -m service -a "name=nginx state=started"
    ~]# ansible all -m shell -a "ss -tnl | grep 80"

--- user：管理用户账号
        *name=
        system=
        uid=
        shell=
        group=
        groups=
        comment=
        home=
    ~]# ansible all -m user -a 'name=test comment="注释"'

--- setup：系统环境
    ~]# ansible 172.18.21.72 -m setup
    ~]# ansible all -m setup
    ~]# ansible web -m setup

            YAML：语法格式
            Playbook的核心元素：
                Hosts：
                Tasks：任务
                Variables
                Templates：包含了模板语法的文本文件；
                Handlers：由特定条件触发的任务；

                Roles

--- group：添加或删除组
            *name=
            state=
            system=
            gid=

--- script：
            -a "/PATH/TO/SCRIPT_FILE"

--- template：基于模板方式生成一个文件复制到远程主机
            *src=
            *dest=
            owner=
            group=
            mode=

--- uri：

------------------------------------------------------------------------------------------------
 1.1   playbook的基础组件：
        Hosts：运行指定任务的目标主机；
        remoute_user: 在远程主机上执行任务的用户；
            sudo_user：
        tasks：任务列表
            模块，模块参数；
            格式：
                (1) action: module arguments
                (2) module: arguments

        注意：shell和command模块后面直接跟命令，而非key=value类的参数列表；

        (1) 某任务的状态在运行后为changed时，可通过“notify”通知给相应的handlers；
        (2) 任务可以通过"tags“打标签，而后可在ansible-playbook命令上使用-t指定进行调用；


1.2：运行playbook的方式：
        (1) 测试
            只检测可能会发生的改变，但不真正执行操作；
            ansible-playbook  --check filename.yml
            列出运行任务的主机；
            ansible-playbook  --list-hosts filename.yml

        (2) 运行
            ansible-playbook filename.yml

handlers：
    任务，在特定条件下触发；
    接收到其它任务的通知时被触发；
    
variables：
    (1) facts：可直接调用；
    (2) ansible-playbook命令的命令行中的自定义变量：
        -e VARS, --extra-vars=VARS
    (3) 通过roles传递变量；
    (4) Host Inventory
        (a) 向不同的主机传递不同的变量；
            IP/HOSTNAME  varaiable=value var2=value2
        (b) 向组中的主机传递相同的变量；
            [groupname:vars]
            variable=value
            
        注意：invertory参数：
            用于定义ansible远程连接目标主机时使用的参数，而非传递给playbook的变量；
                ansible_ssh_host
                ansible_ssh_port
                ansible_ssh_user
                ansible_ssh_pass
                ansbile_sudo_pass
            ...



            
            
    playbook的其它组件
        
        变量：
            ansible facts
            ansible-playbook  -e "var=value"
            host variable: host iventory
            group variable
                [groupname:vars]
                var=value
            roles
            
            调用：{{ variable }}
            
            在playbook中定义变量的方法：
            vars:
            - var1: value1
            - var2: value2
            
        模板：templates
            文本文件，嵌套有脚本（使用模板编程语言编写）
                Jinja2：
                    字面量：
                        字符串：使用单引号或双引号；
                        数字：整数，浮点数；
                        列表：[item1, item2, ...]
                        元组：(item1, item2, ...)
                        字典：{key1:value1, key2:value2, ...}
                        布尔型：true/false
                        
                    算术运算：
                        +, -, *, /, //, %, **
                        
                    比较操作：
                        ==, !=, >, >=, <, <=
                        
                    逻辑运算：
                        and, or, not 
                        
                示例： 
                - hosts: websrvs
                remote_user: root
                tasks:
                    - name: install nginx
                    yum: name=nginx state=present
                    - name: install conf file
                    template: src=files/nginx.conf.j2 dest=/etc/nginx/nginx.conf
                    notify: restart nginx
                    tags: instconf
                    - name: start nginx service
                    service: name=nginx state=started
                    handlers:
                    - name: restart nginx
                    service: name=nginx state=restarted                 
                        
                    模板配置文件 ：nginx.conf.j2
                    worker_processes {{ ansible_processor_vcpus }};
                    listen {{ http_port }};
                    
        条件测试：
            when语句：在task中使用，jinja2的语法格式
                tasks: 
                - name: install conf file to centos7
                  template: src=files/nginx.conf.c7.j2
                  when: ansible_distribution_major_version == "7"
                - name: install conf file to centos6
                  template: src=files/nginx.conf.c6.j2
                  when: ansible_distribution_major_version == "6"               
        
        循环：迭代，需要重复执行的任务；
            对迭代项的引用，固定变量名为”item“
            而后，要在task中使用with_items给定要迭代的元素列表；
                列表方法：
                    字符串
                    字典
                                    
            - name: install some packages
              yum: name={{ item }} state=present
              with_items:
              - nginx
              - memcached
              - php-fpm
              
            - name: add some groups
              group: name={{ item }} state=present
              with_items:
              - group11
              - group12
              - group13
            - name: add some users
              user: name={{ item.name }} group={{ item.group }} state=present
              with_items:
              - { name: 'user11', group: 'group11' }
              - { name: 'user12', group: 'group12' }
              - { name: 'user13', group: 'group13' }
              
    角色(roles)：
        角色集合：
            roles/
                mysql/
                httpd/
                nginx/
                memcached/
                
        每个角色，以特定的层级目录结构进行组织：
            mysql/
                files/ ：存放由copy或script模块等调用的文件；
                templates/：template模块查找所需要模板文件的目录；
                tasks/：至少应该包含一个名为main.yml的文件；其它的文件需要在此文件中通过include进行包含；
                handlers/：至少应该包含一个名为main.yml的文件；其它的文件需要在此文件中通过include进行包含；
                vars/：至少应该包含一个名为main.yml的文件；其它的文件需要在此文件中通过include进行包含；
                meta/：至少应该包含一个名为main.yml的文件，定义当前角色的特殊设定及其依赖关系；其它的文件需要在此文件中通过include进行包含；
                default/：设定默认变量时使用此目录中的main.yml文件；
                
        在playbook调用角色方法1：
            - hosts: websrvs
              remote_user: root
              roles:
              - mysql
              - memcached
              - nginx
            
        在playbook调用角色方法2：传递变量给角色
            - hosts: 
              remote_user:
              roles:
              - { role: nginx, username: nginx }
                键role用于指定角色名称；后续的k/v用于传递变量给角色；
                
            还可以基于条件测试实现角色调用；
            roles:
            - { role: nginx, when: "ansible_distribution_major_version == '7' " }
            
    实战项目：
        主/备模式高可用keepalived+nginx(proxy)
        两台主机：httpd+php
        一台主机：mysql-server或mariadb-server；
    
    http://www.ansible.com.cn



--------------------------------------------------------------------

~]# vi first.yml

    - hosts: all 
      remote_user: root
      tasks:
      - name: create a user3
        user: name=user3 system=yes uid=307
      - name: create a user4
        user: name=user4 system=true uid=308


~]# ansible all -m shell -a "id user3"
~]# ansible all -m shell -a "id user4"

]# ansible-playbook --list-hosts first.yml





--------------------------------------------------------------------

~]# web.yml
- hosts: web
  remote_user: root
  tasks:
  - name: install httpd package
    yum: name=httpd state=present
    tags: insthttpd
  - name: install configure file
    copy: src=files/httpd.conf dest=/etc/httpd/conf/
    tags: instconf
    notify: restart httpd
  - name: start httpd service
    service: name=httpd state=started 
    tags: servicehttpd
    tags: instconf
  handlers:
  - name: restart httpd
    service: name=httpd state=restarted




~]# ansible-playbook  web.yml
~]# ansible web -m shell -a "ss -tnl | grep 80"
~]# ansible-playbook -t instconf --check web.yml
~]# ansible-playbook -t servicehttpd web.yml
~]# ansible-playbook -t instconf --check web.yml

不执行显示级的任务。












--------------------------------------------------------------------
~]# four.yml
- hosts: web
  remote_user: root
  tasks:
  - name: install {{ pkname }}
    yum: name={{ pkname }} state=present

~]# ansible-playbook -e pkname=memcached four.yml 




--------------------------------------------------------------------

~]# vi hostname.yml 
- hosts: web
  remote_user: root
  tasks:
  - name: set hostname
    hostname: name={{ hname }}

~]# ansible-playbook  hostname.yml
~]# ansible web -a "hostname"






--------------------------------------------------------------------
[web]
172.18.21.72 http_port=809
172.18.21.73 http_port=8089


[root@localhost roles]# cat nginx.yml 
- hosts: web
  remote_user: root
  tasks:
  - name: install nginx
    yum: name=nginx state=present
  - name: install conf file
    template: src=files/nginx.conf.j2 dest=/etc/nginx/nginx.conf
    notify: restart nginx
    tags: instconf
  - name: start nginx service
    service: name=nginx state=started
  handlers:
  - name: restart nginx
    service: name=nginx state=restarted




~]# cat files/nginx.conf.j2
listen       {{ http_port }};
#worker_processes {{ ansible_processor_vcpus }};
worker_processes {{ ansible_processor_vcpus+1 }};
--------------------------------------------------------------------

[root@localhost roles]# cat user.yaml 
- hosts: all
  remote_user: root
  tasks:
  - name: create user
    group: name={{ item }} state=present
    with_items:
    - group11
    - group12
    - group13
  - name: add some users
    user: name={{ item.name }} group={{ item.group }} state=present
    with_items:
    - { name: 'user11',group: 'group11' }
    - { name: 'user12',group: 'group12' }
    - { name: 'user13',group: 'group13' }
--------------------------------------------------------------------
~]# mkdir /etc/ansible/roles/nginx/{files,tasks,templates,handlers,vars,default,meta} -pv

mkdir /etc/ansible/roles/{nginx,php-fpm,memcached}/{files,tasks,templates,handlers,vars,default,meta} -pv

nginx/
├── default
├── files
├── handlers
│   └── main.yml
├── meta
├── tasks
│   └── main.yml
├── templates
│   └── nginx.conf.j2
└── vars

ansible-playbook  /etc/ansible/ansible/nginx.yml 

[root@localhost nginx]# cat /etc/ansible/ansible/nginx.yml 
- hosts: web
  remote_user: root
  roles:
  - nginx



cat /etc/ansible/ansible/nginx.yml 
- hosts: web
  remote_user: root
  roles:
  - { role:  nginx, username: nginx }







内存空间总量：
"ansible_memtotal_mb": 475,










---------------------------------------------------------------------------

[root@localhost ansible]# cat myuser.yml 
- hosts: all
  remote_user: root
  vars:
  - username: testuser1
  - groupname: testgroup1
  tasks:
  - name: create group
    group: name={{ groupname }} state=present
  - name: create user
    user: name={{ username }} state=present

~]# ansible-playbook -e "groupname=testgroup2" --check myuser.yml
~]# ansible-playbook -e "groupname=testgroup3" -e "username=testuser3"  myuser.yml


~]# ansible-playbook -t instconf -e "username=adm"  /etc/ansible/ansible/nginx.yml











